#include "../include/user_manager.h"
#include "../include/db_manager.h"
#include <sstream>
#include <iomanip>
#include <random>
#include <chrono>
#include <functional>

UserManager::UserManager() {
}

UserManager::~UserManager() {
}

bool UserManager::registerUser(const std::string& username, const std::string& password,
                              const std::string& phone, const std::string& email) {
    // Call database manager to create user (password will be automatically encrypted in DBManager)
    DBManager db_manager;
    return db_manager.createUser(username, password, phone, email);
}

bool UserManager::loginUser(const std::string& username, const std::string& password, int& user_id) {
    // Call database manager to authenticate user
    DBManager db_manager;
    return db_manager.authenticateUser(username, password, user_id);
}

bool UserManager::getUserInfo(int user_id, std::map<std::string, std::string>& user_info) {
    // Call database manager to get user information
    DBManager db_manager;
    return db_manager.getUserInfo(user_id, user_info);
}

bool UserManager::updateUserInfo(int user_id, const std::map<std::string, std::string>& user_info) {
    // This should call the database manager to update user information
    return true;
}

std::string UserManager::encryptPassword(const std::string& password) {
    // Use more secure hash algorithm (simulating SHA-256)
    std::string salt = "cpp_search_salt_2024"; // Fixed salt, should be different per user in real applications
    std::string salted_password = password + salt;
    
    std::hash<std::string> hasher;
    std::stringstream ss;
    
    // Multiple hashes for increased security
    std::string hash_str = salted_password;
    for (int i = 0; i < 1000; ++i) {
        hash_str = std::to_string(hasher(hash_str)) + salted_password;
        hash_str = std::to_string(hasher(hash_str));
    }
    
    ss << std::hex << std::hash<std::string>{}(hash_str);
    return ss.str();
}

bool UserManager::verifyPassword(const std::string& password, const std::string& encrypted_password) {
    return encryptPassword(password) == encrypted_password;
}

std::string UserManager::generateSessionId(int user_id) {
    // Generate random session ID
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 15);
    
    std::stringstream ss;
    ss << std::hex << user_id << "_";
    for(int i = 0; i < 32; i++) {
        ss << dis(gen);
    }
    return ss.str();
}

bool UserManager::validateSession(const std::string& session_id, int& user_id) {
    // Parse session ID to get user ID
    size_t pos = session_id.find('_');
    if (pos == std::string::npos) {
        return false;
    }
    
    try {
        user_id = std::stoi(session_id.substr(0, pos), nullptr, 16);
        return true;
    } catch (...) {
        return false;
    }
}

std::string UserManager::generateRandomString(int length) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 35);
    
    const std::string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
    std::string result;
    for(int i = 0; i < length; i++) {
        result += chars[dis(gen)];
    }
    return result;
}

std::string UserManager::getCurrentTimestamp() {
    auto now = std::chrono::system_clock::now();
    auto time_t = std::chrono::system_clock::to_time_t(now);
    std::stringstream ss;
    ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
    return ss.str();
}